/**
 * 
 */
package com.fs.jzzn.service;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

import lombok.AllArgsConstructor;
import lombok.Data;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.fs.base.utils.ApplicationUtils;
import com.fs.jzzn.pojo.Flow;
import com.fs.jzzn.pojo.FlowProcess;
import com.fs.jzzn.pojo.FlowStatus;
import com.fs.jzzn.pojo.Project;
import com.fs.jzzn.repository.FlowProcessRepository;
import com.fs.jzzn.repository.FlowRepository;
import com.fs.jzzn.repository.FlowStatusRepository;

/**
 * @author Administrator
 */
@Transactional
@Service("flowService")
@AllArgsConstructor
@Data
public class FlowService {
	FlowRepository flowRepository;
	FlowStatusRepository flowStatusRepository;
	FlowProcessRepository flowProcessRepository;
	
	/**
	 * 获取流程模板的第一个节点
	 * @param ftempId
	 * @return
	 */
	public Flow getFirstNode(String ftempId){
		return flowRepository.getFirstNode(ftempId);
	}
	
	/**
	 * 获取当前节点所属流程的下一个节点
	 * @param ftempId
	 * @param nodeId
	 * @return
	 */
	public Flow getNextNode(String ftempId,String nodeId){
		Flow nextNode = null;
		Flow node = null;
		List<Flow> nodeList = flowRepository.findByParentIdOrderByFlowOrderAsc(ftempId);
		if(nodeList!=null){
			int len = nodeList.size();
			for(int i=0;i<len;i++){
				node = nodeList.get(i);
				if(node.getId().equals(nodeId) && (i+1)<len){
					nextNode = nodeList.get(i+1);
					break;
				}
			}
		}
		return nextNode;
	}
	
	/**
	 * 获取上一个流程节点
	 * @param ftempId
	 * @param nodeId
	 * @return
	 */
	public Flow getPreNode(String ftempId,String nodeId){
		Flow preNode = null;
		Flow node = null;
		List<Flow> nodeList = flowRepository.findByParentIdOrderByFlowOrderAsc(ftempId);
		if(nodeList!=null){
			int len = nodeList.size();
			for(int i=0;i<len;i++){
				node = nodeList.get(i);
				if(node.getId().equals(nodeId) && (i-1)>=0){
					preNode = nodeList.get(i-1);
					break;
				}
			}
		}
		return preNode;
	}
	
	
	/**
	 * 获取当前流程实例的执行流程节点
	 * @param ftempId
	 * @param modelId
	 * @return
	 */
	public Flow getCurrentNode(String ftempId, String modelId){
		Flow node = null;
		FlowStatus fs = flowStatusRepository.findByFlowIdAndModleId(ftempId, modelId);
		if(fs!=null && StringUtils.isNotBlank(fs.getNodeId())){
			node = flowRepository.findOne(fs.getNodeId());
		}
		return node;
	}
	
	/**
	 * 流程执行
	 * @param ftempId
	 * @param modelId
	 * @return
	 */
	@Transactional
	public FlowStatus action(String ftempId,String modelId,String className){
		FlowStatus instance = null;
		Flow template = flowRepository.findOne(ftempId);
		if(template!=null){
			instance = flowStatusRepository.findByFlowIdAndModleId(ftempId, modelId);
			if(instance==null){
				instance = start(ftempId, modelId,className);
			}
			/*
			 * 处理人匹配
			 */
			String userid = ApplicationUtils.userId();
			Set<String> userIdSet = userKeySet(instance.getNodeUserId());
			if(instance!=null && StringUtils.isNotBlank(instance.getNodeId()) &&userIdSet.contains(userid)){
				recordProcess(instance,userid, instance.getNodeName().concat("处理完毕！"));
			}
		}
		return instance;
	}
	
	@Transactional
	public void nextNode(FlowStatus fs){
		FlowStatus instance = flowStatusRepository.findOne(fs.getId());
		Flow nextNode = getNextNode(instance.getFlowId(), instance.getNodeId());
		instance.setNodeId(nextNode.getId());
		instance.setNodeName(nextNode.getFlowName());
		instance.setNodeUserId(nextNode.getActiveUserIds());
		flowStatusRepository.save(instance);
	}
	
	/**
	 * 流程节点回退
	 * @param project
	 */
	@Transactional
	public void preNode(Project project,Flow node) {
		FlowStatus instance = null;
		if(project!=null && node!=null){
			instance = flowStatusRepository.findByFlowIdAndModleId(project.getFlowId(), project.getId());
			instance.setNodeId(node.getId());
			instance.setNodeName(node.getFlowName());
			instance.setNodeUserId(node.getActiveUserIds());
			flowStatusRepository.save(instance);
		}
	}
	
	/**
	 * 流程启动，创建流程实例
	 * @param ftempId
	 * @param modelId
	 */
	private FlowStatus start(String ftempId,String modelId,String className){
		FlowStatus fs = null;
		Flow firstNode = flowRepository.getFirstNode(ftempId);
		if(firstNode!=null){
			String userid = firstNode.getActiveUserIds();
			if(StringUtils.isBlank(userid)){
				userid = ApplicationUtils.userId();
			}
			fs = new FlowStatus(ftempId,modelId, userid, firstNode.getId(),firstNode.getFlowName(),className);
			fs = flowStatusRepository.save(fs);
		}
		return fs;
		
	}
	
	@Transactional
	public void recordProcess(FlowStatus fs,String userId,String msg){
		FlowProcess process = new FlowProcess(
				fs.getId(), 
				fs.getModleId(), 
				fs.getNodeId(),
				fs.getNodeName(),
				userId,
				msg
		);
		flowProcessRepository.save(process);
	}
	
	private Set<String> userKeySet(String userIds){
		Set<String> idSet = new HashSet<String>();
		if(StringUtils.isNotBlank(userIds)){
			for(String id: userIds.split(",")){
				idSet.add(id);
			}
		}
		return idSet;
	}
	/**
	 * 判断当前节点处理人是否有权利操作此节点
	 * @param userId
	 * @param modleId
	 * @return
	 */
	public boolean isRight(String userId,String modelId,String ftempId){
		Flow template = flowRepository.findOne(ftempId);
		//节点处理人id
		String nodeUserId = "";
		
		FlowStatus instance = null;
		if(template!=null){
			instance = flowStatusRepository.findByFlowIdAndModleId(ftempId, modelId);
			if(instance==null){
				//流程未启动取第一个流程节点
				Flow firstNode = flowRepository.getFirstNode(ftempId);
				if(firstNode!=null && StringUtils.isNotBlank(firstNode.getActiveUserIds())  ){
					nodeUserId = firstNode.getActiveUserIds();
				}
			}else{
				nodeUserId = instance.getNodeUserId();
			}
		}
		if(StringUtils.isBlank(nodeUserId)){
			nodeUserId = userId;
		}
		return userKeySet(nodeUserId).contains(userId);
	}
}
